#include "rendermanager.h"
#include "videographicview.h"

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
RenderManager& RenderManager::Instance()
{
    static RenderManager mgr;
    return mgr;
}

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void RenderManager::Init(QWidget* parent, IRenderHandler* handler)
{
    m_parent_wnd = parent;
    m_handler = handler;
}

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void RenderManager::Update1x2Display()
{
    QSize parent_size = m_parent_wnd->size();

    IRenderView* left_view = m_renders[0]->view;
    IRenderView* right_view = m_renders[1]->view;

    left_view->SetGeometry(0, parent_size.height() / 4,
                           parent_size.width() / 2, parent_size.height() / 2);

    right_view->SetGeometry(parent_size.width() / 2, parent_size.height() / 4,
                            parent_size.width() / 2, parent_size.height() / 2);
}

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void RenderManager::UpdateNxNDisplay(uint32_t n)
{
    QSize parent_size = m_parent_wnd->size();

    for (auto index = 0; index < m_renders.size(); index++) {
        m_renders[index]->view->SetGeometry(
            (index % n) * parent_size.width() / n,
            (index / n) * parent_size.height() / n,
            parent_size.width() / n,
            parent_size.height() / n);
    }
}

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void RenderManager::UpdateRenderDisplay()
{
    size_t render_count = m_renders.size();

    if (render_count == 0) return;

    if (render_count == 1) {
        UpdateNxNDisplay(1);
    }
    else if (render_count == 2) {
        Update1x2Display();
    }
    else if (render_count <= 4) {
        UpdateNxNDisplay(2);
    }
    else if (render_count <= 9) {
        UpdateNxNDisplay(3);
    }
    else {
        // Do nothing
    }

    for (auto& item : m_renders) {
        item->view->Show();
    }
}

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void* RenderManager::AddRender(const std::string& render_id)
{
    std::lock_guard<std::mutex> lock(m_mutex);

    if (m_renders.size() >= 9) {
        return nullptr;
    }

    RenderEntrySP renderer(new RenderEntry());
    renderer->id = render_id;
    renderer->view = new WidgetView(render_id, m_handler, m_parent_wnd);

    m_renders.push_back(renderer);

    UpdateRenderDisplay();

    return (void*)renderer->view->WinId();
}

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void RenderManager::RemoveRender(const std::string& render_id)
{
    std::lock_guard<std::mutex> lock(m_mutex);

    for (auto it = m_renders.begin(); it != m_renders.end(); it++) {
        if ((*it)->id == render_id) {
            delete (*it)->view;
            m_renders.erase(it);
            UpdateRenderDisplay();
            return;
        }
    }
}

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void* RenderManager::FindRender(const std::string& render_id)
{
    std::lock_guard<std::mutex> lock(m_mutex);

    for (auto it = m_renders.begin(); it != m_renders.end(); it++) {
        if ((*it)->id == render_id) {
            return (void*)((*it)->view->WinId());
        }
    }

    return nullptr;
}

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void RenderManager::UpdateLabelText(const std::string& render_id,
                                    const std::string& text)
{
    std::lock_guard<std::mutex> lock(m_mutex);

    for (auto& item : m_renders) {
        if (item->id == render_id) {
            if (item->view) {
                item->view->UpdateLabelText(text);
            }
            break;
        }
    }
}
